Skip to content

test(gates): the two document-count pins allow up to two words between numeral and noun - #7915

Merged
os-sam merged 1 commit into
mainfrom
claude/issue-7888-count-pin-adjacency-narrowness
Sep 6, 2026
Merged

test(gates): the two document-count pins allow up to two words between numeral and noun#7915
os-sam merged 1 commit into
mainfrom
claude/issue-7888-count-pin-adjacency-narrowness

Conversation

@claude

@claude claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Fixes #7888

objectui#7448 landed the same document-count pin in two gate test files and stated the rule in both docstrings as "a numeral DIRECTLY qualifying a document-population noun". Both implemented it as strict adjacency, so a single adjective inside the noun phrase defeated them. This brings the implementation up onto the declaration by carrying the third copy's pattern (objectui#7825, PR objectui#7885) to both twins verbatim.

The measurement, re-verified in this branch

objectui#7448's regex run verbatim over check-links.yml's header as it stood on origin/main at 83fe6e741 — a header carrying two live drifted counts:

PRE-FIX check-links.yml header (83fe6e741):
  twin  => ["183 files"]
  third => ["15 INTERNAL documents","183 files"]

One of two. The count the adjacent-only pattern scores clean is the one that had drifted furthest (15 against a measured 17), because an adjective sits between the numeral and the noun.

What changed

The pattern only, in the two files the card names, plus the docstring sentence that described it:

- \b\d+\s+`?(?:\.mdx|\.md|documents?|pages?|docs?|files?)\b
+ NEGLOOKBEHIND\d+(?:,\d{3})*\s+(?:[A-Za-z][\w-]*\s+){0,2}`?(?:\.mdx|\.md|documents?|pages?|docs?|files?)\b

NEGLOOKBEHIND above stands for a negative lookbehind over the character class of #, word characters and a dot, written out as a word on purpose: that group opens with the same two characters a body sanitizer treats as the start of a markup declaration, and this repository has measured such fragments being eaten inside fenced code blocks. The literal is in the diff, which is authoritative.

Up to two intervening words; issue references ruled out at the pattern level by a negative lookbehind rather than by luck; noun set unchanged. No fourth spelling was invented — this is check-links-workflow.test.ts's pattern, character for character. The word DIRECTLY leaves the docstrings: keeping it would only have inverted the same gap between what the pin claims and what it does.

Latent, not live — re-verified, and the grading holds

Both twin workflow headers are clean under both patterns on this branch's base (84ce0b80d):

doc-fence-languages.yml:  twin => [] | third => []
doc-component-types.yml:  twin => [] | third => []

No claim on either header is false today. This closes a proven hole; it is not firefighting.

Positive controls — four directions, each twin

A pin that cannot fail is not a pin. Each mutation was injected into the workflow header the pin actually reads, proven on disk first (injected-hit count plus blob hash), and each restore was proven by state (git diff HEAD empty and blob back to the HEAD blob), restoring with git checkout HEAD -- ABSOLUTE_PATH so a written index could not hand the mutation back.

direction injected doc-fence-languages doc-component-types
A — the shape that was missed holds 15 INTERNAL documents EXIT=1, 1 failed / 25 passed EXIT=1, 1 failed / 53 passed
B — restore (none) EXIT=0, 26 passed EXIT=0, 54 passed
C — a number correct today 227 covered documents / 188 scanned documents EXIT=1 EXIT=1
D — reverse control, issue ref #7448 documents the rule EXIT=0, 26 passed EXIT=0, 54 passed

Both A and C name the pin in the failure, e.g.

FAIL scripts/__tests__/check-doc-fence-languages.test.ts >
  its header states the population and never counts it — no count can rot here
AssertionError: doc-fence-languages.yml's header states a document count (227 covered documents). ...
  expected [ '227 covered documents' ] to deeply equal []

Direction C is objectui#7448's own ablation design and the one that matters most: 227 is the live figure check:doc-fences prints today, and 188 is what check:doc-types prints today. Both are refused anyway. The pin governs this class of writing, not "a wrong number" — a pin that only rejected wrong numbers would wave the same trap through tomorrow when the number happened to be right.

Restore evidence, both twins, all legs:

RESTORED: git diff HEAD empty AND blob back to HEAD blob 179f1c9eb62c9855aaed84900b22c2f115d67647   (doc-fence-languages.yml)
RESTORED: git diff HEAD empty AND blob back to HEAD blob 18e8bbdbb004b0275a139fcb2dbde0c157a59bcf   (doc-component-types.yml)

The new pattern is strictly better, not merely wider

Running both patterns over the three control shapes:

shape old (adjacent-only) new
holds 15 INTERNAL documents [] — missed ["15 INTERNAL documents"]
the 227 covered documents ... [] — missed ["227 covered documents"]
#7448 documents the rule ["7448 documents"]false positive []

The third row was not part of the card and is worth recording: the old pattern read an issue reference directly followed by a population noun as a document count. The negative lookbehind removes a false positive at the same time as it widens the true-positive reach.

Clause 5 — the tightened pattern's reach on today's tree, measured not assumed

Tightening a predicate can turn green things red, so this was measured before shipping.

On the surfaces these two pins read: zero. Both twin headers are empty under the new pattern (above), so no currently-green pin turns red.

Repo-wide census over all 34 workflow headers, for the record and for the seat that takes objectui#7901:

changeset-release.yml      twin => ["161 files","73 files"]   third => ["0 pending changeset file","161 files","73 files"]
cross-repo-issue-closer.yml twin => ["37 pages"]              third => ["37 pages"]
TOTAL: twin=3 hits in 2 files | third=4 hits in 2 files       DELTA = 1

The single new hit is Removed 0 pending changeset file(s) — a quoted log line, not a population claim, and in a workflow no pin reads. Both files are outside this pin family's coverage entirely, so nothing here changes any check's colour. Flagging it because a future coverage widening would have to decide about it.

Ordering, for the next seat

This card (narrowness) had to precede objectui#7901 (coverage: all three copies read .github/workflows/*.yml headers and none reads content/docs/**). Had the order been reversed, objectui#7901's census would have counted coverage using a known-narrow regex and scored its misses as absences. That ordering no longer needs re-deriving.

Out of scope, filed

objectui#7914 — neither twin has an in-file positive control. Each pin holds one assertion against a header that is empty today, so both would pass identically if the pattern were deleted. The third copy carries a fixture block; the twins do not. The four-direction demonstration above had to be run out of band. Not carried here because this card's file surface is the patterns only.

Verification

Gate union re-run after the final commit, on the pushed SHA caaafd30b, with git diff HEAD empty:

vitest (repo ROOT, both twin files)  EXIT=0   Test Files 2 passed (2)   Tests 80 passed (80)
node scripts/check-doc-fence-languages.mjs    EXIT=0
node scripts/check-doc-component-types.mjs    EXIT=0
node scripts/check-control-bytes.mjs          EXIT=0   scanned 6396 tracked text file(s)
node scripts/check-lint-coverage.mjs          EXIT=0   46/46 packages linted
eslint --format json (the 2 edited files)     EXIT=0   files: 2, errors: 0, warnings: 0

vitest was invoked from the repository root, so the objectui#3378 false green (a package-dir cwd silently running apps/console's 22 files) is excluded: the run reports RUN v4.1.10 /home/user/objectui-issue-7888 and 2 test files, not 22.

The eslint run is a declared narrowing, and here is why it measures the whole question. Population read from ESLint's own config resolution rather than a guess about which files count: of 6,481 tracked files, 4,331 are js/ts-shaped and isPathIgnored puts 4,329 of them in the linted population, both edited files included. File count linted comes from --format json: 2. Invariance: eslint.config.js declares no projectService and no parserOptions.project, so no rule is type-aware and this diff cannot move the verdict on any file it did not touch. The repo-wide run is CI's.

Changeset checker verdict, quoted verbatim and obeyed rather than reasoned about:

Compared the working tree with 84ce0b80d (merge-base with origin/main): 2 file(s) changed, 0 of them
published source of a package the release covers, 0 of them a manifest whose published contract moved,
0 under a package changesets ignores, 0 changeset(s) added.
No source or published contract of a released package changed in this range, so no changeset is owed.

Governed-surface guard, quoted verbatim:

NOT GOVERNED — 2 path(s) checked against 5 governed surface(s); none matched.
   An ordinary pull request: the normal review and merge-queue route applies.

Left as draft: the PM seat runs the three pre-landing checks and drives the merge queue.


Generated by Claude Code

…n numeral and noun

objectui#7448 landed the same document-count pin in two gate test files and
stated the rule in both docstrings as "a numeral DIRECTLY qualifying a
document-population noun". Both implemented it as strict adjacency, so a single
adjective inside the noun phrase defeated them.

Measured, not inferred. #7448's regex run verbatim over `check-links.yml`'s
header as it stood on origin/main at 83fe6e7 — a header carrying two live
drifted counts — reports one of the two:

  twin  regex => ["183 files"]
  third regex => ["15 INTERNAL documents","183 files"]

The count it scores clean is the one that had drifted furthest (15 against a
measured 17), because an adjective sits between the numeral and the noun.

This carries the third copy's pattern (objectui#7825, PR #7885,
`check-links-workflow.test.ts`) to both twins verbatim: up to two intervening
words, issue references excluded at the pattern level by a negative lookbehind
rather than by luck, noun set unchanged. No fourth spelling is invented. The
docstrings drop "DIRECTLY" — keeping it would only have inverted the same gap
between what the pin claims and what it does.

Latent, not live: both twin workflow headers are clean under both patterns on
today's tree, so this closes a proven hole rather than a live violation.

Part of objectui#7888

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants